//********************************************************************
//	created:	12:10:2011   21:30
//	filename: 	mysqldatabase.cpp
//	author:		tiamo
//	purpose:	mysql database
//********************************************************************

#include "stdafx.h"
#include "mysqldatabase.h"

namespace mysql
{
	//
	// error
	//
	void Database::sqlError(bool throwException, MYSQL_STMT* sqlStatement)
	{
		char const* sqlErr													= sqlStatement ? mysql_stmt_error(sqlStatement) : mysql_error(mConnection);
		UniString errorMessage												= utils::utf8ToWide(sqlErr);
		close();
		if(throwException)
			ThrowException(L"mysql::Database(%p): sql error (%ls)", this, errorMessage.c_str());
	}

	//
	// close
	//
	void Database::close()
	{
		if(mConnection)
			mysql_close(mConnection);

		mConnection															= nullptr;
	}

	//
	// open
	//
	void Database::open(UniString const& host, UniString const& userName, UniString const& password, UniString const& database)
	{
		mHost																= host;
		mUserName															= userName;
		mPassword															= password;
		mDatabase															= database;

		open();
	}

	//
	// open
	//
	void Database::open()
	{
		if(mConnection || mHost.empty())
			return;

		mConnection															= mysql_init(0);
		if(!mConnection)
			return;

		if(!mysql_real_connect(mConnection, utils::wideToUtf8(mHost).c_str(), utils::wideToUtf8(mUserName).c_str(), utils::wideToUtf8(mPassword).c_str(), utils::wideToUtf8(mDatabase).c_str(), 0, 0, 0))
			return sqlError(false);

		if(mysql_set_character_set(mConnection, "utf8"))
			return sqlError();

		if(mysql_autocommit(mConnection, false))
			return sqlError();
	}

	//
	// start transaction
	//
	void Database::startTransaction()
	{
		open();

		if(!mConnection)
			ThrowException(L"mysql::Database(%p): open database first");

		if(mysql_query(mConnection, "start transaction"))
			return sqlError();
	}

	//
	// commit transaction
	//
	void Database::commitTransaction()
	{
		open();

		if(!mConnection)
			ThrowException(L"mysql::Database(%p): open database first");

		if(mysql_commit(mConnection))
			return sqlError();
	}

	//
	// rollback transcation
	//
	bool Database::rollbackTransaction()
	{
		if(!mConnection)
			return false;

		if(mysql_rollback(mConnection))
			return sqlError(false), false;

		return true;
	}

	//
	// get last inserted it
	//
	uint64_t Database::getlastInsertedId()
	{
		open();

		if(!mConnection)
			ThrowException(L"mysql::Database(%p): open database first");

		return static_cast<uint64_t>(mysql_insert_id(mConnection));
	}

	//
	// create stmt
	//
	Statement Database::createStatement()
	{
		//
		// open connection
		//
		open();
		if(!mConnection)
			ThrowException(L"mysql::Database(%p): open database first");

		//
		// initialize statement
		//
		MYSQL_STMT* sqlStatement											= mysql_stmt_init(mConnection);
		if(!sqlStatement)
			sqlError(true);

		return Statement(sqlStatement, *this);
	}
}
